package com.matrix.geo.playmysqlgeo.typehandler;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKBReader;
import org.locationtech.jts.io.WKBWriter;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

@MappedTypes(Geometry.class)
@MappedJdbcTypes(JdbcType.OTHER)
public class SQLServerGeometryTypeHandler extends BaseTypeHandler<Geometry> {

    private final WKBReader wkbReader = new WKBReader();

    private final WKBWriter wkbWriter = new WKBWriter();

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Geometry parameter, JdbcType jdbcType) throws SQLException {
        byte[] wkb = wkbWriter.write(parameter);
        ps.setBytes(i, wkb);
    }

    @Override
    public Geometry getNullableResult(ResultSet rs, String columnName) throws SQLException {
        byte[] wkb = rs.getBytes(columnName);
        return toGeometry(wkb);
    }

    @Override
    public Geometry getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        byte[] wkb = rs.getBytes(columnIndex);
        return toGeometry(wkb);
    }

    @Override
    public Geometry getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        byte[] wkb = cs.getBytes(columnIndex);
        return toGeometry(wkb);
    }

    // 将二进制数据转换为 JTS 几何对象
    private Geometry toGeometry(byte[] wkb) {
        if (wkb == null) {
            return null;
        }
        try {
            return wkbReader.read(wkb);
        } catch (ParseException e) {
            throw new RuntimeException("Failed to convert SQL Server geometry to JTS geometry.", e);
        }
    }

}
